/*
 * @Author: cooper
 * @Date: 2025-03-30 21:35:19
 * @Wechat: cmd_develop
 * @Description: 机械臂驱动
 */
#include "./bsp_temputure.h"
#include "string.h" // 用于 memcpy
temputure_buffer temputure_Buffer;

static SemaphoreHandle_t temputure_uart_rx_sem = 0; // 串口接受信号量
static SemaphoreHandle_t temputure_uart_tx_sem = 0; // 串口发送信号量
QueueHandle_t temputure_message_queue = 0;          // temputure消息邮箱,确保消息ok
QueueHandle_t temputure_work_queue = 0;             // 长轴工作邮箱

// MKS接收数据处理任务句柄
TaskHandle_t temputure_uart_receive_task_handler;
TaskHandle_t temputure_work_task_handler;

// 为了方便阅读函数，将基本函数写在文件最后
void TEMPUTURE_UART_DMA_RX(void);
void TEMPUTURE_UART_DMA_TX(u16 size);
void DMA1_Channel1_IRQHandler(void);

void temputure_uart_receive_task(void *parameter);

u8 temputure_moto_function(u8 addr, u8 moto_do, u32 pos);

void RX_temputure_handle(void);

/*************************************** 4号RS485——temputure DMA配置 ***************************************/
/**
 * @brief  temputure串口DMA接收
 * @param  none
 * @retval none
 */

void TEMPUTURE_TASK(void)
{
    // 串口初始化
    TEMPUTURE_UART_INIT();
    // 初始化信号量
    temputure_uart_rx_sem = xSemaphoreCreateBinary();
    temputure_uart_tx_sem = xSemaphoreCreateBinary();
    xSemaphoreGive(temputure_uart_tx_sem); // 释放发送信号量

    temputure_message_queue = xQueueCreate((UBaseType_t)1,  /* 消息队列的长度 */
                                           (UBaseType_t)1); /* 消息的大小 */

    temputure_work_queue = xQueueCreate((UBaseType_t)1,  /* 消息队列的长度 */
                                        (UBaseType_t)4); /* 消息的大小 */

    // 创建接收任务
    xTaskCreate((TaskFunction_t)temputure_uart_receive_task,
                (const char *)"TEMPUTURE_RX_TASK",
                (uint16_t)configMINIMAL_STACK_SIZE, // 128
                (void *)NULL,
                (UBaseType_t)4,
                (TaskHandle_t *)&temputure_uart_receive_task_handler);
}

// 任务函数，等待信号量并处理接收到的数据
void temputure_uart_receive_task(void *parameter)
{
    while (1)
    {
        // 等待信号量，直到有数据接收
        if (xSemaphoreTake(temputure_uart_rx_sem, portMAX_DELAY) == pdTRUE)
        {
            // logPrintln("temputure_RX_FUNCTION:");
            // for (int i = 0; i <= RX_temputure_TOTAL - 1; i++)
            // {
            //     logPrintln("i:%d:%x\t", i, temputure_Buffer.rx_data[i]);
            // }
            // logPrintln("\n");
            RX_temputure_handle();
        }
    }
}

void RX_temputure_handle(void)
{
    // 等待信号量，直到 DMA 接收完成
    u16 crc_data = 0;
    u16 message_crc = 0;
    u8 message_crc8 = RX_temputure(RX_temputure_TOTAL - 1);

    /* 确定 （地址+功能） 符合 */
    if ((RX_temputure(0) == TX_temputure(0)) && (RX_temputure(1) == TX_temputure(1)))
    {
        /* 获取数据帧的CRC */
        message_crc = RX_temputure(RX_temputure_TOTAL - 2) + (RX_temputure(RX_temputure_TOTAL - 1) << 8);
        /* 计算数据帧的CRC */
        crc_data = usMBCRC16(&RX_temputure(0), RX_temputure_TOTAL - 2);
        /* 校验 */
        if (message_crc == crc_data)
        {
            switch (RX_temputure(1))
            {
                // 读取数据保存
            case 0x03:
                u16 slave_addr = TX_temputure(0);                                    /* 从机地址 */
                u16 slave_regaddr = (u16)((TX_temputure(2) << 8) + TX_temputure(3)); /* 寄存器地址 */
                u16 regaddr_total = (u16)(RX_temputure(2) / 2);                      /* 寄存器个数 */
                switch (slave_regaddr)
                {
                case 10: // 10号地址起始是读取温度
                    for (u8 i = 0; i < regaddr_total; i++)
                    {
                        //BP_CONFIG[(slave_addr * 3 - 3) + i].cur_temputure = (u16)((RX_temputure(3 + 2 * i) << 8) + RX_temputure(4 + 2 * i));
                        // Read_Temperature((slave_addr * 3 - 2) + i) = (u16)((RX_temputure(3 + 2 * i) << 8) + RX_temputure(4 + 2 * i));
                    }
                    break;
                default:
                {
                }
                break;
                }
                break;
                // xSemaphoreGive(Temperature_connect_semaph); // 释放信号量
                TX_temputure_BufClear(); // 清空缓存
            }
        }
        TEMPUTURE_UART_DMA_RX(); // RX准备接受下一次数据
    }
}

/**
 * @brief  温控主机轮询函数
 * @param  none
 * @retval none
 */
void Temperture_Master_Work_FUNCTION(u8 addr)
{
}

/*************************************** 烤位管理 ***************************************/
/**
 * @brief  	烤位温度加热
 * @param1  	烤位序号
 * @param2  	烤位温度
 * @retval 	none
 */
void kw_temperautre_control(u8 kw_num, u8 temperature)
{
}

/**
 * @brief  	烤位温度加热
 * @param1  	烤位序号
 * @param2  	肠盒号
 * @retval 	none
 */
void kw_heat_temperautre(u8 kw_num, u8 taste)
{
}

/**
 * @brief  	烤位温度保温
 * @param1  	烤位序号
 * @param2  	肠盒号
 * @retval none
 */
void kw_keep_temperautre(u8 kw_num, u8 taste)
{
}

/**
 * @brief  烤位温度清除
 * @param  烤位序号
 * @retval none
 */
void kw_clear_temperautre(u8 kw_num)
{
}
/// @brief 机械臂长轴发送命令
/// @param
void temputure_cmd_queue_send(u8 code[3])
{
    logPrintln("temputure_cmd_queue_send");

    xQueueSend(temputure_work_queue, // 发送队列句柄
               code,                 // 发送内容
               0);                   // 对满不等待
}

/// @brief
/// @param addr 从机地址
/// @param moto_do 电机去干什么：归零、位置移动
/// @param pos 位置参数
/// @return
u8 temputure_moto_function(u8 addr, u8 moto_do, u32 pos)
{

    return 0;
}

/// @brief temputure串口DMA接受
/// @param
void TEMPUTURE_UART_DMA_RX(void)
{
    dma_init_type dma_init_struct;
    /* 使能时钟 */
    crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
    /* 使能dma复用功能 */
    dmamux_enable(DMA1, TRUE);
    /* 复位指定的 DMA 通道 */
    dma_reset(DMA1_CHANNEL3);
    /* 默认填充配置 */
    dma_default_para_init(&dma_init_struct);
    /* DMA 传输数据量+传输方向 */
    dma_init_struct.buffer_size = temputure_DATA_SIZE;
    dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
    /* 外设地址+数据宽度+地址增加模式 */
    dma_init_struct.peripheral_base_addr = (uint32_t)&UART5->dt;
    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
    dma_init_struct.peripheral_inc_enable = FALSE;
    /* 存储器地址+数据宽度+地址增加模式 */
    dma_init_struct.memory_base_addr = (uint32_t)(&(RX_temputure(0)));
    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
    dma_init_struct.memory_inc_enable = TRUE;
    /* 优先级+循环模式 */
    dma_init_struct.priority = DMA_PRIORITY_HIGH;
    dma_init_struct.loop_mode_enable = FALSE;
    /* 初始化指定的 DMA 通道 */
    dma_init(DMA1_CHANNEL3, &dma_init_struct);
    /* 初始化dma复用功能 */
    dmamux_init(DMA1MUX_CHANNEL3, DMAMUX_DMAREQ_ID_UART5_RX);
    /* 使能指定通道 */
    dma_channel_enable(DMA1_CHANNEL3, TRUE);
    /* 清空数据 */
    RX_temputure_BufClear();
}

/**
 * @brief  temputure串口DMA发送
 * @param  none
 * @retval none
 */
void TEMPUTURE_UART_DMA_TX(u16 size)
{
    dma_init_type dma_init_struct;
    /* 使能时钟 */
    crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
    /* 使能dma复用功能 */
    dmamux_enable(DMA1, TRUE);
    /* 复位指定的 DMA 通道 */
    dma_reset(DMA1_CHANNEL3);
    /* 默认填充配置 */
    dma_default_para_init(&dma_init_struct);
    /* DMA 传输数据量+传输方向 */
    dma_init_struct.buffer_size = size;
    dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
    /* 存储器地址+数据宽度+地址增加模式 */
    dma_init_struct.memory_base_addr = (uint32_t)(&(TX_temputure(0)));
    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
    dma_init_struct.memory_inc_enable = TRUE;
    /* 外设地址+数据宽度+地址增加模式 */
    dma_init_struct.peripheral_base_addr = (uint32_t)&UART5->dt;
    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
    dma_init_struct.peripheral_inc_enable = FALSE;
    /* 优先级+循环模式 */
    dma_init_struct.priority = DMA_PRIORITY_HIGH;
    dma_init_struct.loop_mode_enable = FALSE;
    /* 使能DMA发送完成中断 */
    dma_interrupt_enable(DMA1_CHANNEL3, DMA_FDT_INT, TRUE);
    nvic_irq_enable(DMA1_Channel3_IRQn, 2, 2);
    /* 初始化指定的 DMA 通道 */
    dma_init(DMA1_CHANNEL3, &dma_init_struct);
    /* 初始化dma复用功能 */
    dmamux_init(DMA1MUX_CHANNEL3, DMAMUX_DMAREQ_ID_UART5_TX);
    /* 使能指定通道 */
    dma_channel_enable(DMA1_CHANNEL3, TRUE);
}

/**
 * @brief  4号RS485——temputure初始化
 * @param  none
 * @retval none
 */
void TEMPUTURE_UART_INIT(void)
{
    gpio_init_type gpio_init_struct;
    /* 使能时钟 */
    crm_periph_clock_enable(CRM_UART5_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOE_PERIPH_CLOCK, TRUE);
    /* GPIO配置 */
    gpio_default_para_init(&gpio_init_struct);
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_pins = GPIO_PINS_10 | GPIO_PINS_11;
    gpio_init(GPIOE, &gpio_init_struct);
    /* 复用 */
    gpio_pin_mux_config(GPIOE, GPIO_PINS_SOURCE10, GPIO_MUX_8);
    gpio_pin_mux_config(GPIOE, GPIO_PINS_SOURCE11, GPIO_MUX_8);
    /* 串口参数 */
    usart_reset(UART5);
    usart_init(UART5, 9600, USART_DATA_8BITS, USART_STOP_1_BIT);
    usart_transmitter_enable(UART5, TRUE);
    usart_receiver_enable(UART5, TRUE);
    /* 中断配置 */
    nvic_irq_enable(UART5_IRQn, 2, 2);
    usart_interrupt_enable(UART5, USART_IDLE_INT, TRUE);
    /* 使用DMA */
    usart_dma_receiver_enable(UART5, TRUE);
    usart_dma_transmitter_enable(UART5, TRUE);
    /* 使能 */
    usart_enable(UART5, TRUE);
    /* DMA接收 */
    TEMPUTURE_UART_DMA_RX();
}

/**
 * @brief  temputure串口3中断处理函数
 * @param  none
 * @retval none
 */
void UART5_IRQHandler(void)
{
    uint32_t ulReturn;
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    /* 进入临界段，临界段可以嵌套 */
    ulReturn = taskENTER_CRITICAL_FROM_ISR();
    if (usart_flag_get(UART5, USART_IDLEF_FLAG) != RESET)
    {
        dma_channel_enable(DMA1_CHANNEL3, FALSE);
        dma_flag_clear(DMA1_FDT3_FLAG);
        // 获取接收总数
        RX_temputure_TOTAL = temputure_DATA_SIZE - dma_data_number_get(DMA1_CHANNEL3);
        // 释放信号量
        xSemaphoreGiveFromISR(temputure_uart_rx_sem, &xHigherPriorityTaskWoken);
        // 切换任务
        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
        usart_flag_clear(UART5, USART_IDLEF_FLAG);
    }
    /* 退出临界段 */
    taskEXIT_CRITICAL_FROM_ISR(ulReturn);
}

/**
 * @brief  temputure串口DMA1通道1中断处理函数
 * @param  none
 * @retval none
 */
void DMA1_Channel3_IRQHandler(void)
{
    uint32_t ulReturn;
    /* 进入临界段，临界段可以嵌套 */
    ulReturn = taskENTER_CRITICAL_FROM_ISR();
    if (dma_interrupt_flag_get(DMA1_FDT3_FLAG))
    {
        TEMPUTURE_UART_DMA_RX(); // 准备接收
        dma_flag_clear(DMA1_FDT3_FLAG);
    }
    /* 退出临界段 */
    taskEXIT_CRITICAL_FROM_ISR(ulReturn);
}
